
package com.whoimi.common;

import com.fasterxml.jackson.annotation.JsonInclude;

import java.io.Serial;
import java.io.Serializable;
import java.util.Objects;


public class ResultInfo<T> implements Serializable {

    @Serial
    private static final long serialVersionUID = -8949153510458566367L;

    /**
     * 作为交易成功失败的唯一标准
     */
    private Boolean success;
    /**
     * 用于区分失败类型
     */
    @JsonInclude(JsonInclude.Include.NON_NULL)
    private Integer resultCode;
    /**
     * 失败描述
     */
    @JsonInclude(JsonInclude.Include.NON_NULL)
    private String resultMsg;
    /**
     * 业务内容返回体
     */
    @JsonInclude(JsonInclude.Include.NON_NULL)
    private T resultBody;

    private void initSuccess() {
        this.success = true;
        this.resultCode = Constant.CODE_OK;
        this.resultMsg = Constant.MSG_OK;
    }

    private void initFail() {
        this.success = false;
        this.resultCode = Constant.CODE_FAIL;
        this.resultMsg = Constant.MSG_FAIL;
    }

    public ResultInfo() {
        super();
    }

    public ResultInfo(Boolean success) {
        super();
        if (success) {
            this.initSuccess();
        } else {
            this.initFail();
        }

    }

    public ResultInfo(Boolean success, String resultMsg) {
        super();
        if (success) {
            this.initSuccess();
        } else {
            this.initFail();
        }
        this.resultMsg = resultMsg;

    }

    public ResultInfo(T resultBody) {
        this.initSuccess();
        this.resultBody = resultBody;
    }

    public ResultInfo(ResultEnum resultEnum) {
        super();
        this.success = Objects.equals(resultEnum.getResultCode(), Constant.CODE_OK);
        this.resultCode = resultEnum.getResultCode();
        this.resultMsg = resultEnum.getResultMsg();
    }

    public ResultInfo(Boolean success, T resultBody) {
        super();
        if (success) {
            this.initSuccess();
        } else {
            this.initFail();
        }
        this.resultBody = resultBody;
    }

    public ResultInfo(Integer resultCode) {
        if (Constant.CODE_OK.equals(resultCode)) {
            this.initSuccess();
        } else {
            this.initFail();
        }
        this.resultCode = resultCode;
    }

    public ResultInfo(Boolean success, Integer resultCode) {
        this(success);
        this.resultCode = resultCode;
    }

    public ResultInfo(Integer resultCode, String resultMsg) {
        this(resultCode);
        this.resultMsg = resultMsg;
    }

    public ResultInfo(Boolean success, Integer resultCode, String resultMsg) {
        this(success, resultCode);
        this.resultMsg = resultMsg;
    }

    public ResultInfo(Integer resultCode, String resultMsg, T resultBody) {
        this(resultCode, resultMsg);
        this.resultBody = resultBody;
    }

    public ResultInfo(Boolean success, Integer resultCode, String resultMsg, T resultBody) {
        this(success, resultCode, resultMsg);
        this.resultBody = resultBody;
    }


    /**
     * @return 成功信息, 不包含BODY
     */
    public static <T> ResultInfo<T> ok() {
        return new ResultInfo<>(true);
    }

    /**
     * @param resultBody resultBody
     * @return 成功包含BODY
     */
    public static <T> ResultInfo<T> ok(T resultBody) {
        return new ResultInfo<>(true, resultBody);
    }

    /**
     * 成功包含所有信息
     *
     * @param resultCode    resultCode
     * @param resultMessage resultMessage
     * @param resultBody    body
     * @return 成功包含所有信息
     */
    public static <T> ResultInfo<T> ok(Integer resultCode, String resultMessage, T resultBody) {
        return new ResultInfo<>(true, resultCode, resultMessage, resultBody);
    }

    /**
     * @return Fail 不包含信息
     */
    public static <T> ResultInfo<T> fail() {
        return new ResultInfo<>(false);
    }

    public static <T> ResultInfo<T> fail(String resultMsg) {
        return new ResultInfo<>(false, resultMsg);
    }

    public static <T> ResultInfo<T> fail(Integer resultCode, String resultMsg) {
        return new ResultInfo<>(false, resultCode, resultMsg);
    }

    /**
     * 失败信息【不建议使用，FAIL时一般不包含BODY信息】
     *
     * @param resultCode resultCode
     * @param resultMsg  resultMsg
     * @param resultBody resultBody
     * @param <T>        resultBody
     * @return ResultInfo
     */
    public static <T> ResultInfo<T> fail(Integer resultCode, String resultMsg, T resultBody) {
        ResultInfo<T> resultInfo = new ResultInfo<>(false, resultCode, resultMsg);
        resultInfo.setResultBody(resultBody);
        return resultInfo;
    }

    public Boolean getSuccess() {
        return success;
    }

    public void setSuccess(Boolean success) {
        this.success = success;
    }

    public Integer getResultCode() {
        return resultCode;
    }

    public void setResultCode(Integer resultCode) {
        this.resultCode = resultCode;
    }

    public String getResultMsg() {
        return resultMsg;
    }

    public void setResultMsg(String resultMsg) {
        this.resultMsg = resultMsg;
    }

    public T getResultBody() {
        return resultBody;
    }

    public void setResultBody(T resultBody) {
        this.resultBody = resultBody;
    }

    public ResultInfo<T> msg(String msg) {
        this.resultMsg = msg;
        return this;
    }

    public static class Constant {
        public final static Integer CODE_OK = 200;
        public final static Integer CODE_FAIL = 500;
        public final static String MSG_OK = "OK";
        public final static String MSG_FAIL = "FAIL";

    }

    public enum ResultEnum {

        RESULT_SUCCESS(Constant.CODE_OK, Constant.MSG_OK),
        RESULT_FAIL(Constant.CODE_FAIL, Constant.MSG_FAIL),
        SMS_TIMEOUT(452, "短信验证码超时,请重新提交");
        private final Integer resultCode;
        private final String resultMsg;
        private static final ResultEnum[] VALUES;

        static {
            VALUES = values();
        }

        ResultEnum(Integer resultCode, String resultMsg) {
            this.resultCode = resultCode;
            this.resultMsg = resultMsg;
        }

        public Integer getResultCode() {
            return resultCode;
        }


        public String getResultMsg() {
            return resultMsg;
        }


        public static ResultEnum valueOf(Integer resultCode) {
            ResultEnum resolve = resolve(resultCode);
            if (resolve == null) {
                throw new IllegalArgumentException("No matching constant for [" + resultCode + "]");
            }
            return resolve;
        }

        public static ResultEnum resolve(Integer resultCode) {
            for (ResultEnum status : VALUES) {
                if (Objects.equals(status.resultCode, resultCode)) {
                    return status;
                }
            }
            return null;
        }
    }
}
